package cn.t.service.device;

import cn.t.constants.CommonConstants;
import cn.t.core.service.ServiceImpl;
import cn.t.model.device.CargowayDO;
import cn.t.model.device.CargowaySkuDO;
import cn.t.model.device.DeviceDO;
import cn.t.model.sku.SkuDO;
import cn.t.repository.device.CargowayRepository;
import cn.t.repository.device.CargowaySkuRepository;
import cn.t.repository.device.DeviceRepository;
import cn.t.repository.sku.SkuRepository;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * 货道商品表(CargowaySku)领域服务
 *
 * @author t
 * @since 2024-05-24 10:19:11
 */
@Slf4j
@Service
@AllArgsConstructor
public class CargowaySkuService extends ServiceImpl<CargowaySkuDO, CargowaySkuRepository> {

    private final CargowayRepository cargowayRepository;
    private final SkuRepository skuRepository;
    private final FaultService faultService;
    private final DeviceRepository deviceRepository;

    public Boolean addUpdateBatch(List<CargowaySkuDO> cargowayDOS) {
        return  this.repository.addOrUpdateBatch(cargowayDOS);
    }
    public Boolean updateBatch(List<CargowaySkuDO> cargowayDOS) {
        return  this.repository.updateBatch(cargowayDOS);
    }
    public List<CargowaySkuDO> getDeviceSkuList(List<Long> deviceIds) {
        CargowaySkuDO queryParams = new CargowaySkuDO();
        queryParams.setDeviceIds(deviceIds);
        return this.findByModel(queryParams, CommonConstants.ZERO, Integer.MAX_VALUE, null, null);
    }

    public List<CargowaySkuDO> getCargowaySku(List<String> skuCodes, Long cargowayId) {
        CargowaySkuDO queryParams = new CargowaySkuDO();
        queryParams.setSkuCodes(skuCodes);
        queryParams.setCargowayId(cargowayId);
        return this.findByModel(queryParams, CommonConstants.ZERO, Integer.MAX_VALUE, null, null);
    }
    public List<CargowaySkuDO> getCargowaySkuByDeviceId(List<String> skuCodes, Long deviceId) {
        CargowaySkuDO queryParams = new CargowaySkuDO();
        queryParams.setSkuCodes(skuCodes);
        queryParams.setDeviceId(deviceId);
        return this.findByModel(queryParams, CommonConstants.ZERO, Integer.MAX_VALUE, null, null);
    }
    public void createCargowayGoods( List<CargowaySkuDO> onShelfGoods, List<CargowayDO> onShelfCargoWayList, List<CargowaySkuDO> offShelfGoods, Map<String, SkuDO> updateGoodsMap) {

        if (!CollectionUtils.isEmpty(onShelfGoods)){
            this.addUpdateBatch(onShelfGoods);
        }
        if (!CollectionUtils.isEmpty(onShelfCargoWayList)) {
            cargowayRepository.addOrUpdateBatch(onShelfCargoWayList);
        }
        if (!updateGoodsMap.isEmpty()){
            List<SkuDO> updateGoodsBeans = new ArrayList<>(updateGoodsMap.values());
            skuRepository.addOrUpdateBatch(updateGoodsBeans);
            for (SkuDO sku : updateGoodsBeans) {
                this.repository.update(sku.getSkuCode(), sku);
            }
        }
        batchOffShelf(offShelfGoods);
    }

    public void batchOffShelf(List<CargowaySkuDO> cargowaySkuList) {
        if (CollectionUtils.isEmpty(cargowaySkuList)){
            return;
        }
        this.repository.removeBatch(cargowaySkuList);
        List<Long> cargoWayIds = cargowaySkuList.stream().distinct().map(CargowaySkuDO::getCargowayId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(cargoWayIds)){
            CargowayDO cargowayDO = new CargowayDO();
            cargowayDO.setCargowayVol(CommonConstants.ONE);
            cargowayRepository.update(cargowayDO, cargoWayIds);
        }
    }

    // 更新冗余的sku信息
    public void updateRedundancySkuInfo(SkuDO sku) {

        if (!StringUtils.hasText(sku.getSkuCode())) {
            return;
        }

        this.repository.update(sku.getSkuCode(), sku);
    }

    public List<CargowaySkuDO> getGroupBySku(List<Long> deviceIds) {
        return repository.getGroupBySku(deviceIds);
    }

    public List<CargowaySkuDO> getNoAndIntervery(Long deviceId, String skuCode) {
        return repository.getNoAndIntervery(deviceId, skuCode);
    }

    public Map<String, List<String>> getSkuLocation(List<String> skuCodes, List<Long> deviceIds) {

        // 查询故障库位
        List<Long> faultCargowayList = faultService.getFaultCargowayIds(deviceIds);
        List<CargowaySkuDO> cargowaySkuDOS = this.getCargowaySku(skuCodes, null);
        Map<String, List<CargowaySkuDO>> cargowaySkuMap = cargowaySkuDOS.stream().filter(f -> !faultCargowayList.contains(f.getCargowayId())).collect(Collectors.groupingBy(CargowaySkuDO::getSkuCode));

        // 查询设备信息
        deviceIds = CollectionUtils.isEmpty(deviceIds) ? cargowaySkuDOS.stream().map(CargowaySkuDO::getDeviceId).collect(toList()) : deviceIds;
        DeviceDO queryParams = new DeviceDO();
        queryParams.setDeviceIds(deviceIds);
        List<DeviceDO> devices = this.deviceRepository.findByModel(queryParams, CommonConstants.ZERO, Integer.MAX_VALUE, null, null);
        Map<String, DeviceDO> deviceMap = devices.stream().collect(Collectors.toMap(DeviceDO::getImei, Function.identity(), (a, b) -> a));
        Map<Long, String> deviceIdImeiMap = devices.stream().collect(Collectors.toMap(DeviceDO::getId, DeviceDO::getImei));

        Map<String, List<String>> skuCargowayInfoMap = new HashMap<>();
        cargowaySkuMap.forEach((skuCode, val) -> {

            val.forEach(f -> f.setImei(deviceIdImeiMap.get(f.getDeviceId())));

            Map<String, List<CargowaySkuDO>> deviceSkuMap = val.stream().filter(f -> StringUtils.hasText(f.getImei())).collect(Collectors.groupingBy(CargowaySkuDO::getImei));
            List<String> cargowayInfo = new ArrayList<>();
            deviceSkuMap.forEach((imei, value) -> {
                // 查询设备
                DeviceDO device = deviceMap.get(imei);
                String deviceName = device == null ? CommonConstants.BLANK : device.getDeviceName();
                String cargowayNos = value.stream().map(f -> String.valueOf(f.getCargowayNo())).collect(Collectors.joining(","));
                cargowayInfo.add("货柜名称: " + deviceName +";货道: " + cargowayNos);
            });
            skuCargowayInfoMap.put(skuCode, cargowayInfo);
        });

        return skuCargowayInfoMap;
    }
}
